package br.com.felix.filediff;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import br.com.felix.util.ILogDevice;

/**
 * Class the helps comparing two folders.
 * */
public class FileDiff {

	
	/**
	 * Returns a list of differences found when comparting two folders.
	 * @param origin is the "LEFT" folder of the comparison.
	 * @param target is the "RIGHT" folder of the comparison.
	 * @see FileDiffResult
	 * */
	public static List<FileDiffResult> fileDiff(List<FileDiffResult>lstResult, File origin, File target, ILogDevice log){
		log.log("Examining '"+origin.getAbsolutePath()+"' against '"+target.getAbsolutePath()+"'.");
		for(File f:origin.listFiles()){
			if(f.isDirectory()){
				File[] diretorioNoDestino = target.listFiles(new SingleFileFilenameFilter(f));
				if(diretorioNoDestino.length==0){
					directoryIsNew(lstResult,f);
				}
				else{
					fileDiff(lstResult, f, diretorioNoDestino[0], log);
				}
			}
			else{
				lstResult.add(checkFile(f, target));
			}
		}
		return lstResult;
	}

	
	/**
	 * Navigates through the directory structure marking subfolders as ONLY_IN_LEFT.
	 * */
	private static void directoryIsNew(List<FileDiffResult> lstResult, File folder) {
		FileDiffResult fdiff = new FileDiffResult();
		fdiff.file = folder;
		fdiff.diffStatus = DiffStatus.ONLY_IN_LEFT;
		lstResult.add(fdiff);
		
		for(File f: folder.listFiles()){
			if(f.isDirectory()){
				directoryIsNew(lstResult, f);
			}
			else{
				FileDiffResult fdr = new FileDiffResult();
				fdr.file = f;
				fdr.diffStatus = DiffStatus.ONLY_IN_LEFT;
				lstResult.add(fdr);
			}
		}
	}


	/**
	 * Compares files from two different directories and returns the result.
	 * @see FileDiffResult
	 * */
	private static FileDiffResult checkFile(File f, File destino) {
		File[] files = destino.listFiles(new SingleFileFilenameFilter(f));
		FileDiffResult fdr = new FileDiffResult();
		fdr.file = f;
		if(files.length==0){
			fdr.repositoryFile = null;
			fdr.diffStatus = DiffStatus.ONLY_IN_LEFT;
		}
		else{
			fdr.repositoryFile = files[0];
			if(files[0].length()== f.length()){
				fdr.diffStatus = DiffStatus.FILES_ARE_EQUAL;
			}
			else{
				fdr.diffStatus = DiffStatus.FILES_ARE_DIFFERENT;
			}
		}
		return fdr;
	}
	
	
	public static void main(String args[]){
		List<FileDiffResult> lstResult = new ArrayList<FileDiffResult>();
		fileDiff(lstResult, new File(args[0]), new File(args[1]), new ILogDevice(){
			public void log(String str) {
				System.out.println(str);
			}
			public void error(String msg, Exception e) {
				log(msg+"; "+e.getMessage());
			}
			@Override
			public boolean errorHasOcurred() {
				// TODO Auto-generated method stub
				return false;
			}
			@Override
			public void lookForErrorsAgain() {
				// TODO Auto-generated method stub
				
			}
		});
		Pattern p = Pattern.compile("\\.svn");
		Matcher m;
		for(FileDiffResult fdr:lstResult){
			m = p.matcher(fdr.file.getAbsolutePath());
			if(fdr.diffStatus!=DiffStatus.FILES_ARE_EQUAL && !m.find()){
				System.out.printf("%-80s %-20s\n", fdr.file.getAbsolutePath(),fdr.diffStatus.toString());
			}
		}
	}
}
